Sideshift: query both old and new affiliate accounts and merge completed orders - #220
Sideshift: query both old and new affiliate accounts and merge completed orders#220j0ntz wants to merge 2 commits into
Conversation
b21225d to
c439b81
Compare
Live dual-account smoke test (throwaway affiliate accounts)Verified the old + new merge end to end against the live Sideshift API, using two throwaway affiliate accounts created via
Fresh affiliate accounts have no order history, so (A)/(B)/(C) confirm the live query, signature, and cursor-map plumbing, while (D) feeds one realistic settled order per account into the live query loop so the real processing + merge path produces a combined non-empty stream. Combined with the deterministic unit tests in The throwaway accounts were used only for this read-only test and carry no funds. |
c439b81 to
ecde277
Compare
4e6e2b0 to
b308478
Compare
Code reviewFound 4 issues:
edge-reports-server/src/partners/sideshift.ts Lines 356 to 372 in 0a6ba03
edge-reports-server/src/partners/sideshift.ts Lines 365 to 372 in 0a6ba03
edge-reports-server/src/partners/sideshift.ts Lines 423 to 426 in 0a6ba03 edge-reports-server/src/queryEngine.ts Lines 276 to 285 in 0a6ba03
edge-reports-server/src/partners/sideshift.ts Lines 276 to 284 in 0a6ba03 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
|
Addressed the review findings above (fixup commit pushed, unit tests added):
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 9f244ba. Configure here.
ee1c93b to
9763ac4
Compare
peachbits
left a comment
There was a problem hiding this comment.
I don't think we should skip orders so maybe we eliminate the third commit and most of the 2nd.
9763ac4 to
efe181d
Compare
…ed orders Loop the per-account completed-orders query over each configured affiliate account and merge the streams so a Sideshift affiliate-account rotation keeps reporting the old account's historical and in-flight shifts. Track latestIsoDate per account so neither account's cursor skips the other's orders, falling back to the legacy single cursor for backward compatibility. Single-account config is unchanged. Add a mocha test covering the dual-account merge and per-account cursor behavior. Claude-Session: https://claude.ai/code/session_01YNwNii1LxjqaeowP5d7dgJ
Map bsv (Bitcoin SV) to the bitcoinsv plugin id and add BSV-bsv to the delisted coins map so historical BSV orders resolve instead of throwing "Unknown network: bsv". Claude-Session: https://claude.ai/code/session_01YNwNii1LxjqaeowP5d7dgJ
efe181d to
ee7afde
Compare

CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
none
Description
Asana: https://app.asana.com/0/1215088146871429/1216057011453392
The Sideshift partner plugin queried a single affiliate account, so after the
Sideshift affiliate-account rotation it would drop the previous account's
historical completed orders and miss in-flight shifts still routed under the
previous affiliateId during the App Store update lag.
This changes
src/partners/sideshift.tsto query BOTH affiliate accounts andmerge their completed-order streams, per the rotation decision (query both and
merge to preserve complete history).
What changed:
sideshiftAffiliateId2/sideshiftAffiliateSecret2alongside the existingprimary pair.
apiKeysreaching a plugin is a flat string map (asPartnerInfoin
types.ts), so a nested array is not possible; the explicit numbered pairis the backward-compatible form.
getSideshiftAccountsreturns the primaryaccount plus the optional second account, deduped by affiliateId, and throws if
only one of the
*2fields is set (a half-configured pair is amisconfiguration, not a silent single-account run).
sideshiftAffiliateIdis the PRE-EXISTING account: on the firstrun after deploy it inherits the legacy single
latestIsoDatewatermark, so itresumes incrementally and never re-scans its full history. The
*2pair is aNEWLY-ADDED account with no recorded history, so it backfills from epoch.
Operational consequence at a rotation: put the current (soon-to-be-old) account
in
sideshiftAffiliateIdand the new account in*2. No progress-cache editis needed, and the account with years of history never does a multi-hour
from-epoch crawl. (Reversing the slots would send the established account
through a full from-epoch re-scan.)
querySideshiftAccountand run once per configured account; the streams aremerged into one result.
latestIsoDatecursor is tracked PER account in a newsettings.accountsmap so one account's cursor never skips the other's orders. Legacy progress
docs (single top-level
latestIsoDate, no map) fall back to that value on thefirst run after deploy, so migration is seamless. The top-level
latestIsoDateis kept as the overall max for backward compatibility.
bsv(Bitcoin SV) is added to the network and delisted-coin maps so historicalBSV orders resolve instead of throwing
Unknown network: bsv.skipped, per reviewer preference: a stopped account is noticed, a stray
"skipped order" log is not, so revenue never drops silently. The throw
surfaces through the block-level retry path, so the cursor holds at the bad
order until the mapping is added.
Backward compatible: a single-account config (no second account) behaves exactly
as before. The second account's id/secret are config values ops adds at rotation
time; the code supports two accounts now.
Testing
test/sideshift.test.ts(mocha + chai, deterministic, no live network):single-account, dual-account merge with max overall cursor, legacy progress-doc
migration, per-account cursor isolation, half-configured-pair throw, and
throw-on-unprocessable-order (order not recorded, cursor holds). 9 passing.
tsc --noEmitclean on the changed files.throw-on-unprocessable revert): 1199 orders across the full 5.5-year history
(41 asset/network pairs) all processed cleanly after the BSV mapping, which is
retained.
edge-reports-serveris a backend server with no app/sim surface, so thedual-account merge + cursor logic is covered by the unit tests above. The live
Sideshift API and CouchDB persistence paths are unchanged.
Note
Medium Risk
Changes affiliate reporting sync, cursor persistence, and backfill behavior during account rotation; misconfigured primary vs *2 slots could cause a large epoch re-scan or missed history, though tests cover the main migration paths.
Overview
Extends the Sideshift partner plugin so two affiliate accounts can be queried and their completed-order streams merged, preserving full shift history when the affiliate ID rotates (old account in primary fields, new account in optional
sideshiftAffiliateId2/sideshiftAffiliateSecret2).Cursor / migration behavior: Progress now stores per-account watermarks in
settings.accountswhile keeping top-levellatestIsoDateas the max across accounts. On upgrade, the primary account inherits the legacy single cursor; a second account backfills from epoch so it does not inherit the primary’s advanced watermark and skip history. Half-configured*2fields throw instead of silently running single-account.Implementation: Single-account polling is refactored into
querySideshiftAccountwith injectable fetch/process hooks for tests;getSideshiftAccountsbuilds the account list (deduped, ordered).Asset mapping: Adds
bsv→bitcoinsvand delistedBSV-bsvso historical BSV orders process instead of failing on unknown network.Failure mode: Unprocessable orders still propagate through block retries; the cursor does not advance past a bad order (no silent skip).
Reviewed by Cursor Bugbot for commit ee7afde. Bugbot is set up for automated code reviews on this repo. Configure here.